using System;
using System.Collections;
using System.Collections.Generic;
using CrystalDecisions.Shared;
using CrystalDecisions.CrystalReports.Engine;
using System.IO;
using System.Data;


namespace Mani.Common
{
    public class CrystalReportManager
    {


        private ReportDocument _reportDocument;
        private string _reportName;
        private string _reportPath = System.Web.HttpContext.Current.Server.MapPath("~") + "\\rpt\\";
        private List<object> _parameterValues;
        private List<string> _parameterNames;

        public string ReportPath
        {
            get { return _reportPath; }
            set { _reportPath = value; }
        }
        public List<string> ParameterNames { get { return _parameterNames; } }
        public List<object> ParameterValues { get { return _parameterValues; } }
        public string ReportName { get { return _reportName; } }
        public ReportDocument Report { get { return _reportDocument; } }

        public CrystalReportManager(string _reportname, List<string> _parameternames, List<object> _parametervalues)
        {
            _parameterNames = _parameternames;
            _parameterValues = _parametervalues;
            _reportName = _reportname;
        }

        public void Init(string dbconnectionsource)
        {
            ConfigureCrystalReportsParameters();
            ConfigureCrystalReportLogonInfo(_reportDocument, dbconnectionsource);
        }

        public void Init(string dbconnectionsource, string reportPath)
        {
            _reportPath = reportPath;
            Init(dbconnectionsource);
        }


        public void PrintToPrinter(string printer)
        {
            if (printer == null) printer = "";
            _reportDocument.PrintOptions.PrinterName = printer;
            Print();
        }

        public void PrintToPrinter(string printer, int numberOfCopies)
        {
            if (printer == null) printer = "";
            _reportDocument.PrintOptions.PrinterName = printer;
            Print(numberOfCopies);
        }

        public void PrintToPdf()
        {
            // TODO: HADI: WHY NOT USE EXPORT TO PDF
            _reportDocument.PrintOptions.PrinterName = "Adobe PDF";
            Print();
        }

        private void Print()
        {
            _reportDocument.PrintToPrinter(1, false, 0, 0);
        }

        private void Print(int NumberOfCopies)
        {
            _reportDocument.PrintToPrinter(NumberOfCopies, false, 0, 0);
        }

        public string ExportToDisk(ExportFormatType type)
        {
            string guid = Guid.NewGuid().ToString();
            string fileExtension = "unknown";
            switch (type)
            {
                case ExportFormatType.PortableDocFormat:
                    fileExtension = "pdf";
                    break;
                default:
                    throw new Exception("unknown ExportFormatType: " + type.ToString());
            }


            string tempDirectory = AppDomain.CurrentDomain.BaseDirectory + "Temp";
            Directory.CreateDirectory(tempDirectory + "\\" + guid);
            string filepath = string.Format(tempDirectory + "\\{0}\\{1}." + fileExtension, guid, _reportName);

            _reportDocument.ExportToDisk(type, filepath);
            return filepath;
        }

        public void SetReportDataset(DataSet ds)
        {
            _reportDocument.SetDataSource(ds);
        }

        private void ConfigureCrystalReportsParameters()
        {
            _reportDocument = new ReportDocument();
            _reportPath += _reportName + ".rpt";
            //_reportPath = AppDomain.CurrentDomain.BaseDirectory + _reportPath;
            _reportDocument.Load(_reportPath);

            if (_parameterNames == null)
                return;

            ArrayList arrayListValue = new ArrayList();
            for (int i = 0; i < _parameterValues.Count; i++)
            {
                object id = _parameterValues[i];
                arrayListValue.Add(id);
            }


            ArrayList arrayListName = new ArrayList();
            for (int i = 0; i < _parameterNames.Count; i++)
            {
                object id = _parameterNames[i];
                arrayListName.Add(id);
            }


            ParameterFields parameterFields = _reportDocument.ParameterFields;
            SetCurrentValuesForParameterField(_reportDocument, arrayListName, arrayListValue);
        }


        private void SetCurrentValuesForParameterField(ReportDocument reportDocument, ArrayList arrayListName, ArrayList arrayListValue)
        {
            ParameterValues currentParameterValues = new ParameterValues();
            ParameterDiscreteValue parameterDiscreteValue = new ParameterDiscreteValue();
            ParameterFieldDefinitions parameterFieldDefinitions = _reportDocument.DataDefinition.ParameterFields;


            ParameterFieldDefinition parameterFieldDefinition;
            string str = "";
            int i = 0;
            foreach (object submittedValue in arrayListValue)
            {
                str = arrayListName[i++].ToString();
                //str = Request.QueryString.GetKey( i++ );
                parameterFieldDefinition = parameterFieldDefinitions[str];
                currentParameterValues = parameterFieldDefinition.CurrentValues;
                currentParameterValues.Clear();
                parameterDiscreteValue.Value = submittedValue;
                currentParameterValues.Add(parameterDiscreteValue);
                parameterFieldDefinition.ApplyCurrentValues(currentParameterValues);
                _reportDocument.DataDefinition.ParameterFields.MoveNext();
            }

            // Dirty patch
            if (_reportName.ToLower() == "bill-envelope")
                _reportDocument.DataDefinition.ParameterFields[1].ApplyCurrentValues(currentParameterValues);



        }


        public byte[] ExportToByte(ExportFormatType type)
        {

            // Create a new stream and get the content of reportDocument in a new Stream object.

            Stream str = _reportDocument.ExportToStream(type);

            // Determine file's conetent.
            byte[] fileContent = new byte[str.Length];

            // Read fileContent to created stream.
            str.Read(fileContent, 0, (int)str.Length);

            // Return file's content.
            return fileContent;
        }

        public void Dispose()
        {
            _reportDocument.Close();
            _reportDocument.Dispose();
            _reportDocument = null;
        }


        // HADI: made these static

        public static void ConfigureCrystalReportLogonInfo(ReportDocument _reportDocument, string connStr)
        {

            ConnectionInfo cnni = new ConnectionInfo();

            string str = GetConnectionStringElements(connStr, "Integrated Security");
            if (str == "" || str.ToLower() == "false")
            {
                cnni.IntegratedSecurity = false;
            }
            else
                cnni.IntegratedSecurity = true;

            cnni.UserID = Convert.ToString(GetConnectionStringElements(connStr, "User ID"));
            cnni.Password = Convert.ToString(GetConnectionStringElements(connStr, "Password"));
            cnni.ServerName = GetConnectionStringElements(connStr, "Data Source");
            cnni.DatabaseName = GetConnectionStringElements(connStr, "Initial Catalog");

            CrystalDecisions.CrystalReports.Engine.Tables ts;

            ts = _reportDocument.Database.Tables;

            TableLogOnInfo li = new TableLogOnInfo();

            foreach (CrystalDecisions.CrystalReports.Engine.Table t in ts)
            {
                li = t.LogOnInfo;
                li.ConnectionInfo = cnni;
                t.ApplyLogOnInfo(li);
            }

            for (int i = 0; i < _reportDocument.Subreports.Count; i++)
            {
                CrystalDecisions.CrystalReports.Engine.Tables tbs;

                tbs = _reportDocument.Subreports[i].Database.Tables;

                TableLogOnInfo loi = new TableLogOnInfo();

                foreach (CrystalDecisions.CrystalReports.Engine.Table tb in tbs)
                {
                    loi = tb.LogOnInfo;
                    loi.ConnectionInfo = cnni;
                    tb.ApplyLogOnInfo(loi);
                }
            }

            li.ConnectionInfo = cnni;

            TableLogOnInfos lis = new TableLogOnInfos();
            lis.Add(li);

        }

        private static string GetConnectionStringElements(string connStr, string valueStr)
        {

            int index = connStr.ToLower().IndexOf(valueStr.ToLower());
            if (index > -1)
            {
                string str = connStr.Substring(index + valueStr.Length + 1, connStr.Length - (index + valueStr.Length + 1));
                index = str.IndexOf(';');
                if (index > -1) str = str.Substring(0, index);
                return str;
            }
            else
            {
                return "";
            }
        }

    }
}

